﻿using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Reflection;
using System.IO;

namespace SneakyWeasel.Engine
{
    public sealed class SWEngine : ISWEngine
    {
        #region Properties

        public Form swForm { get; set; }
        public Dictionary<string, ISWPlugin> Plugins = new Dictionary<string, ISWPlugin>();
        public String MainModule { get; set; }

        #endregion

        #region Constructors
        public SWEngine() : this(new Form(), "SWPlugins") { }

        public SWEngine(Form f) : this(f, "SWPlugins") { }

        public SWEngine(string pluginpath) : this(new Form(), pluginpath) { }

        public SWEngine(Form f, string pluginpath)
        {
            swForm = f;
            MainModule = pluginpath;
        }
        #endregion

        #region Start/Stop Methods
        public void Start()
        {
        }

        public void Stop()
        {
        }
        #endregion

        #region Pulse Methods
        public void Pulse()
        {
        }
        #endregion

        #region Load/Unload Methods

        public bool IsLoaded(string pluginName)
        {
            return Plugins.ContainsKey(pluginName);   // check if we have an instance of the plugin
        }

        public bool Load(string name)
        {
            return Load(MainModule, name); // assume
        }

        public bool Load(string dllmoduleName, string pluginName)
        {
            if (IsLoaded(pluginName))    // we've already loaded this.
                return true;            // so return true

            try
            {
                Assembly ass = Assembly.LoadFile(GetPluginAssemblyPath(dllmoduleName));
 
                foreach (Type type in ass.GetTypes())
                {
                    MessageBox.Show(type.ToString());
                    if (type.GetInterface(typeof(ISWPlugin).FullName) != null
                        && type.ToString().Contains(pluginName)  // we are being meh, lenient in naming convention
                        )
                    {
                        MessageBox.Show("Creating: " + type.ToString());
                        Console.WriteLine("Creating something");
                        return Load((ISWPlugin)Activator.CreateInstance(type));
                    }
                }
                throw new Exception("Module " + pluginName + " not found");
            }
            catch(Exception e)
            {
                MessageBox.Show(e.Message, "Exception loading Plugin: " + dllmoduleName); 
                return false; 
            }

        }

        private string GetPluginAssemblyPath(string name)
        {
            Console.WriteLine(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), name + ".dll"));
            return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), name + ".dll");
        }

        public bool Load(ISWPlugin p)
        {
            Plugins.Add(p.GetType().ToString(), p);
            p.OnLoad(this);
            return true;
        }

        public void Unload(ISWPlugin p)
        {
        }
        #endregion
    }


    public interface ISWEngine
    {
        
        #region SWEngine Interface Properties
        // enum WindowsTypes { Form, Window }  // illegal in an interface?
        // WindowsTypes swForm { get; set; }
        Form swForm { get; set; }
        #endregion

        #region SWEngine API Interface Events 
        void Start();
        void Stop();
        void Pulse();

        bool Load(ISWPlugin p);
        void Unload(ISWPlugin p);
        #endregion
    }
}
